import mongoose from 'mongoose';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import User, { IUser } from '../models/User';
import connectToDatabase from './db';


class UserService {
    /**
     * 确保 MongoDB 连接已建立
     */
    private static async connect() {
        if (mongoose.connection.readyState === 0) {
            await connectToDatabase();
        }
    }

    static async getBook(
        Id: string,
    ): Promise<IUser | null> {
        await this.connect()

        // 使用 $slice 操作符来分页获取 content
        const post = await User.findById(Id).select("bookshelf")

        return post || []
    }

    /**
     * 用户注册
     * @param username 用户名
     * @param email 邮箱
     * @param password 密码（明文，将被加密存储）
     * @returns 创建的用户对象
     */
    static async register(username: string, email: string, password: string) {
        await this.connect();  // 确保数据库连接正常

        // 检查邮箱是否已被注册
        const existingUser = await User.findOne({ email });
        if (existingUser) {
            return null
        }

        // 密码加密
        const hashedPassword = await bcrypt.hash(password, 10);

        // 创建并保存新用户
        const newUser = await User.create({
            username,
            email,
            password: hashedPassword
        });

        return newUser;  // 返回创建的用户
    }

    /**
     * 用户登录
     * @param email 用户邮箱
     * @param password 用户密码
     * @returns 登录成功返回 JWT 令牌和用户信息，失败返回 null
     */
    static async login(email: string, password: string) {
        await this.connect();
        const user = await User.findOne({ email });
        if (!user) return null;

        const isMatch = await bcrypt.compare(password, user.password);
        if (!isMatch) return null;

        // 生成 Access Token（短期）
        const token = jwt.sign({ id: user._id }, "i", { expiresIn: '1h' });

        // 生成 Refresh Token（长期）
        const refreshToken = jwt.sign({ id: user._id }, "ii", { expiresIn: '7d' });

        // 存储 refreshToken 到数据库
        user.token = token;
        user.refreshToken = refreshToken;
        await user.save();

        const { _id, bookshelf, avatar, username } = user;  // 使用解构只获取必要字段

        return { token, refreshToken, bookshelf, avatar, username, id: _id } as Pick<IUser, 'token' | 'refreshToken' | 'bookshelf' | 'avatar' | 'username'>;
    }


    /**
     * 更新用户信息
     * @param userId 用户 ID
     * @param updateData 需要更新的字段
     * @returns 更新后的用户对象
     */
    static async updateUser(userId: string, updateData: Partial<IUser>): Promise<IUser | null> {
        await this.connect();
        return User.findByIdAndUpdate(userId, updateData, { new: true });
    }

    static async updatedTime(userId: string, title: string): Promise<IUser | [] | null> {
        await this.connect();

        const today = new Date().toISOString().split("T")[0]; // 获取 "YYYY-MM-DD"
        const user = await User.findById(userId);

        if (!user) {
            console.log("用户不存在");
            return null;
        }

        // 查找 study_time 中是否有今天的记录，并且是相同的 title
        const existingEntry = user.study_time.find((entry: { date: string; title: string }) => entry.date === today && entry.title === title);

        if (existingEntry) {
            // 如果今天已存在该 title，则累加 5 分钟
            await User.updateOne(
                { _id: userId, "study_time.date": today, "study_time.title": title },
                { $inc: { "study_time.$.duration": 2 } }
            );
        } else {
            // 如果今天不存在该 title，则创建新的记录
            await User.updateOne(
                { _id: userId },
                { $push: { study_time: { date: today, duration: 2, title } } }
            );
        }

        console.log("学习时间已更新", title);
        return null; // 返回更新后的用户数据
    }

    static async getTime(id: string) {
        await this.connect();  // 确保数据库连接正常

        const UserTime = await User.findById(id);
        // console.log(UserTime)
        if (!UserTime) {
            return []
        }
        // console.log(UserTime.study_time)
        return UserTime.study_time;
    }

    static async collectBook(userId: string, bookId: string): Promise<IUser | null> {
        await this.connect();

        // 获取用户信息，查看 bookshelf 中是否已经包含 bookId
        const user = await User.findById(userId);

        if (!user) {
            return null;  // 用户不存在，返回 null
        }

        // 判断书籍是否已经存在于 bookshelf 中
        const isBookInShelf = user.bookshelf.includes(bookId);

        if (isBookInShelf) {
            // 如果书籍已存在，从 bookshelf 中删除书籍
            return User.findByIdAndUpdate(
                userId,
                { $pull: { bookshelf: bookId } },  // 使用 $pull 删除书籍
                { new: true }
            );
        } else {
            // 如果书籍不存在，添加书籍到 bookshelf 中
            return User.findByIdAndUpdate(
                userId,
                { $addToSet: { bookshelf: bookId } },  // 使用 $addToSet 添加书籍
                { new: true }
            );
        }
    }


    static async refreshToken(oldRefreshToken: string): Promise<{ token: string; refreshToken: string } | null> {
        await this.connect();

        const user = await User.findOne({ refreshToken: oldRefreshToken });
        if (!user) return null;

        try {
            jwt.verify(oldRefreshToken, "ii");
            // console.log(decoded); // { id: 用户ID, iat: 时间戳, exp: 过期时间 }
            // 生成新的 Access Token 和 Refresh Token
            const newAccessToken = jwt.sign({ id: user._id }, 'i', { expiresIn: '1h' });
            const newRefreshToken = jwt.sign({ id: user._id }, "ii", { expiresIn: '7d' });

            // 更新数据库中的 refreshToken
            user.refreshToken = newRefreshToken;
            await user.save();

            return { token: newAccessToken, refreshToken: newRefreshToken };
        } catch (error) {
            return null; // Refresh Token 过期或无效
        }
    }


    static async logout(userId: string): Promise<boolean> {
        await this.connect();
        const user = await User.findById(userId);
        if (!user) return false;

        user.refreshToken = "";
        await user.save();
        return true;
    }

}

export default UserService;
